Boxes
Volume Number: 1
Issue Number: 4
Column Tag: ASSEMBLY
The “Boxes” Program 
By David E. Smith
Last month we covered menu bars and event loops, but we left out complete desk
accesory support. Figure 1 above shows that we’ve completed desk accessory support
in this month’s “Boxes” program. Full cut and paste is supported in the note pad, and
we have a dialog box to tell about our program. This represents a complete Macintosh
application shell program for any game type application that does not need text editing
within the application window, but wants a standard user interface. Because of the
length of the program, we will have to keep our comments brief and try to expand on
them in coming issues.
Notice that the number of trap calls needed to fully support the standard
applcation interface has increased dramatically since last month. Even a simple
program, if it uses all the Mac features, will touch nearly every ROM manager. This
month’s program adds 27 ROM calls to the listing we presented last month.
TEXT EDIT SUPPORT
The key to full desk accessory support is text editing using cut and paste. Once
this is successfully implemented, the rest is easy. The TextEdit manager handles all
text display and management including the actual cutting and pasting. We don’t have to
do hardly anything except provide a text record for him. This is done with _TENew
trap. We clear room for the returning handle to the text record, push two rectangles
and call the trap to set-up a text edit record on the heap. The rectangles control the
text destination on the screen and the clipping of that text to a display rectange. See the
“Set Up Text Edit” section of our program to see how this is done.
As Bob Denny mentioned in his “C” column, the text edit manager uses our EDIT
menu, so we have to set-up our EDIT menu items in the standard order. Then, the
actual text editing in a desk accessory is done for us by the trap _SysEdit. We check
this trap first if we find the mouse in the edit menu to allow cutting and pasting by a
desk accessory. The only support we need is for each of our EDIT menu item routines to
call the corresponding Text Edit manager call that does the cutting, pasting or clearing
on our text. We push the handle to our text record obtained from _TENew, and let the
ROM routines do it!
MODELESS DIALOG BOXES
Most applications have a “Modal” dialog box that serves as the “About” function
to tell the user about the program. This is the first item in the Apple menu. We’ve
implemented a “Modeless” dialog box here. What that means is the user is free to make
use of other desk accessories or the application itself while the “About” box is being
displayed. This opens up the possiblity of the user again selecting the “About” box,
which would cause TWO dialog boxes to be displayed! Figure 2 shows how our program
allows any number of dialog boxes to be created by the user. This is interesting because
it lets us slide into multiple window support without really doing multiple windows.
Each dialog box is a small window set-up on the heap. The Dialog manager takes care of
most of the upkeep for this mini- window. Notice our dialog box also has two icons in it
as well as some static text. The resource file shows how the icons and static text are
set-up in assembler format so they will be display properly in the “About” box.
Dialog Box Event Support
We have expanded our event loop from last month to include support for the
dialog box. Supposedly the dialog traps check for a dialog box event (_IsDialog event),
and process such an event for us (_Dialogselect), allowing us to be unconcerned about
events affecting the “About” window such as dragging or closing. In actuallity, the
dialog routine for executing dialog events, _Dialogselect is quite limited and checks
must be made in the application event loop to see if some action is required for a dialog
box. Notice in our event loop that we check for a dialog event right after calling
_GetNextEvent and before branching to our standard event routines. Dragging the dialog
window or clicking the go away box in the dialog window are not indicated by the
_Dialogselect routine. Apparently only a click on a control within the dialog box is
returned as a “true” result.
OUR EVENT LOOP
This month our event loop is expanded to handle activate and deactivate events.
We’ve added an OPEN and CLOSE feature to our application FILE menu to allow the user
to selectively open and close the main window for our program. When the window is
open and active, we disable the edit menu items since our application does not support
these. We must then enable them again if our window is deactivated so any desk
accessories can use them. This is done in the activate and deactivate event routines. The
message and modify sections of our event record tell us if the activate was for our
window, and whether we should activate or deactivate.
UPDATE EVENT
The hardest part about our program was getting the update event to work
properly. If our window has been dragged, we will get an update event to re-draw it. I
was having trouble because when I called QDSTUFF to re-draw the window, everything
was going into the dialog box! This was solved by re-setting the current graf port to
our window so that an update calling to QDSTUFF would be sure to draw in our window
and not the dialog box, if it was still hanging around. An update event for a dialog
window is handled by the dialog manager. However a drag event could be a dialog
window. Since our program allows multiple dialog windows, if any of them are dragged,
we re-store the window location so any new dialog windows don‘t run off the screen.
Until a window is dragged, multiple dialog windows appear down and right of the
previous one as shown in figure 2. The “About” routine takes care of this when we
create a new dialog box by incrementing the window location box.
GO AWAY BOX
Another tricky part to dialog boxes was when the “go away” box was clicked. It
seems that _CloseDialog will hang the system if used for modeless dialog boxes where
more than one such box is allocated. So _CloseWindow should be used instead so that the
support structure for the remaining dialog windows is not deleted. In our “HIDE”
routine, if the “go away” box is clicked, we check if it’s a dialog window or our
application window. If it’s the dialog window, we update the window location by backing
it up so that the next dialog window will continue to appear down and to the right of the
previous one. However, if we close all of them back to the origonal starting location for
our chain of dialog windows, we re-set everything so the dialog windows do not appear
to be going backwards! Many of these little concerns will also affect using multiple
windows and so are important to take care of here where things are still easy.
DESK ACCESSORY SUPPORT
Once the text edit record is set up and the EDIT menu items in place, little is
needed to support desk accessories. We find the desk accessory with _GetItem, and then
push the accessory’s name and call _OpenDeskAcc to do it. We also check _SysEdit in
our EDIT menu item routine as mentioned to allow any open desk accessory to do text
editing.
The “About” function reads the dialog itme list from the resource file and opens a
dialog window on the heap in much the same manner as _NewWindow opens a window on
the heap. The “DITL” resource type holds the item list of those controls, text, icons or
whatever that will appear in the dialog box. In our case, we have only static text and
two icons in our “DITL” resource. The first icon is a system icon that displays a note.
The second is one of ours that displays the logo for this program. Note that for this to
work, the “ICON” resource must be used, not the icon list resource, as I found out the
hard way. See the resource file for the assembly format of the “DITL” items.
THE APPLICATION PROGRAM
Our application itself is very simple. It is simply a static window display of a
bunch of boxes created with the QDSTUFF subroutine, called whenever an update event
for our window occours. To make it a little more interesting, the last box drawn is also
filled with a pattern. Patterns are simply 8 bytes of hex information repeated in the
rectangle.A count variable keeps track of the number of boxes drawn and a loop calls
_FrameRect until all the boxes are displayed. Don’t forget to re-set the count for the
next update event! Figure 3 shows the application program output and our
OPEN/CLOSE flip-flop menu items. These serve to hide or display our application
window in a fashon similar to the go away box. Don’t forget, if the window goes away,
you have to have some method of opening it again! Hence the OPEN and CLOSE file menu
items.
Finally, in figure 4, is our linker file, pretty much the same format as last
month. Remember that the signiture byte, “GLAD” appears both in the resource file’s
bundle and identification resources as well as in the linker file. Next month we use this
same shell program, but we concentrate on the application, getting some dynamic
animation in our application window. Stay tuned!
; EXAMPLE ASSEMBLY PROGRAM
; Boxes
; VERSION 23 JAN 85
; (C) MacTutor March 1985
; by David E. Smith
; Macro subset for Toolbox stuff
MACRO _InitGraf = DC.W $A86E|
MACRO _InitWind = DC.W $A912|
MACRO _NewWindow = DC.W $A913|
MACRO _setport = DC.W $A873|
MACRO _InitFont = DC.W $A8FE|
MACRO _InitMenu = DC.W $A930|
MACRO _InitDialog = DC.W $A97B|
MACRO _TEInit = DC.W $A9CC|
MACRO _Initpack = DC.W $A9E5|
MACRO _FlushEvents = DC.W $A032|
MACRO _InitCursor = DC.W $A850|
MACRO _GetNextEvent = DC.W $A970|
MACRO _FrameRect = DC.W $A8A1|
MACRO _TextFont = DC.W $A887|
MACRO _TextFace = DC.W $A888|
MACRO _TextSize = DC.W $A88A|
MACRO _MoveTo = DC.W $A893|
MACRO _DrawString = DC.W $A884|
MACRO _PenSize = DC.W $A89B|